use std::{fmt::Display, path::{PathBuf}};


pub type Result<T> = std::result::Result<T, ConfigError>;

#[derive(Debug)]
pub enum ConfigError {
    NotFound,
    IoError,
    BadFilePath(PathBuf, String),
    BadEnv(String),
    BadType(String, String, String, Option<PathBuf>),
    ParseError(String, PathBuf, String, Option<(usize, usize)>)
}


impl std::error::Error for ConfigError {}

impl Display for ConfigError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ConfigError::NotFound => write!(f, "config file was not found"),
            ConfigError::IoError =>  write!(f, "there was an I/O error while reading the config file"),
            ConfigError::BadFilePath(p, m) => {
                f.write_fmt(format_args!("the config file path({}) is invalid, {}", p.clone().to_string_lossy(), m))
            }
            ConfigError::BadEnv(e) => {
                f.write_fmt(format_args!("the environment specified in `CONFIG_ENV` is invalid, {}", e))
            }
            ConfigError::BadType(n, e, a, _) => {
                write!(f, "type mismatch for '{}'. expected {}, found {}", n, e, a)
            }
            ConfigError::ParseError(s, p, m, _) => {
                f.write_fmt(format_args!("the config file({}) contains invalid TOML {}, {}", p.clone().to_string_lossy(), s, m))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::path::PathBuf;

    use crate::conf::error::ConfigError;


    #[test]
    fn test_config_error() {
        println!("error {}", ConfigError::BadFilePath(PathBuf::from("/test"), "错误的位置".to_string()));
    }
}